// nodejs_demo.js - SecureConfig命令行工具的Node.js演示脚本
const { execSync } = require('child_process');
const fs = require('fs');
const path = require('path');
const util = require('util');

// 设置主密钥环境变量
// 实际使用时请替换为您的真实密钥
process.env.SECURECONFIGMASTERKEY = 'your_master_key_here';

// 计时开始
const startTime = Date.now();

// ANSI颜色代码
const colors = {
    reset: '\x1b[0m',
    bright: '\x1b[1m',
    dim: '\x1b[2m',
    underscore: '\x1b[4m',
    blink: '\x1b[5m',
    reverse: '\x1b[7m',
    hidden: '\x1b[8m',
    
    fg: {
        black: '\x1b[30m',
        red: '\x1b[31m',
        green: '\x1b[32m',
        yellow: '\x1b[33m',
        blue: '\x1b[34m',
        magenta: '\x1b[35m',
        cyan: '\x1b[36m',
        white: '\x1b[37m'
    },
    
    bg: {
        black: '\x1b[40m',
        red: '\x1b[41m',
        green: '\x1b[42m',
        yellow: '\x1b[43m',
        blue: '\x1b[44m',
        magenta: '\x1b[45m',
        cyan: '\x1b[46m',
        white: '\x1b[47m'
    }
};

/**
 * 执行 secureconfig 命令并返回结果
 * @param {string} command 命令名
 * @param  {...string} args 命令参数
 * @returns {object} 命令执行结果
 */
function runSecureconfigCommand(command, ...args) {
    try {
        const fullCommand = ['secureconfig', command].concat(args);
        console.log(`${colors.fg.yellow}正在执行命令: ${fullCommand.join(' ')}${colors.reset}`);
        
        const output = execSync(fullCommand.join(' '), { encoding: 'utf8' });
        
        // 查找JSON开始的位置，处理可能存在的非JSON前缀
        const jsonStart = output.indexOf('{');
        if (jsonStart >= 0) {
            return JSON.parse(output.substring(jsonStart));
        }
        return { output: output.trim() };
    } catch (error) {
        console.error(`${colors.fg.red}执行命令失败: ${error.message}${colors.reset}`);
        if (error.stdout) {
            try {
                const jsonStart = error.stdout.indexOf('{');
                if (jsonStart >= 0) {
                    return JSON.parse(error.stdout.substring(jsonStart));
                }
            } catch {}
        }
        return { status: 'error', message: error.message };
    }
}

/**
 * 打印结果
 * @param {string} title 标题
 * @param {object} result 结果对象
 */
function printResult(title, result) {
    console.log(`\n${colors.fg.cyan}==== ${title} ====${colors.reset}`);
    if (result.status === 'success') {
        console.log(JSON.stringify(result, null, 4));
    } else {
        console.log(`${colors.fg.red}失败: ${result.message || '未知错误'}${colors.reset}`);
    }
}

async function main() {
    try {
        console.log(`\n${colors.fg.cyan}===== 第一部分: 常规加解密操作 =====${colors.reset}`);

        // 1. 创建 json 配置文件
        const jsonName = 'demo_json';
        console.log(`创建 json 配置文件: ${jsonName}`);
        let result = runSecureconfigCommand('create', jsonName, '--type', 'json', '--force');
        printResult('创建 json 配置', result);

        // 2. set-value 仅支持 json
        console.log(`设置 json 配置的值: ${jsonName} app.version = 2.0.0`);
        result = runSecureconfigCommand('set-value', jsonName, 'app.version', '2.0.0');
        printResult('设置 json 配置值', result);

        // 3. get-value 仅支持 json
        console.log(`获取 json 配置的值: ${jsonName} app.version`);
        result = runSecureconfigCommand('get-value', jsonName, 'app.version');
        printResult('获取 json 配置值', result);

        // 4. 创建 text 文件
        const textName = 'demo_text';
        console.log(`创建 text 文件: ${textName}`);
        result = runSecureconfigCommand('create', textName, '--type', 'text', '--force');
        printResult('创建 text 文件', result);

        // 5. 保存明文内容到 text 文件（直接写入文件）
        const textPath = path.join('configs', `${textName}.txt`);
        fs.writeFileSync(textPath, 'Hello, SecureConfig!\n这是一个文本文件。', 'utf8');
        console.log(`已写入明文内容到 ${textPath}`);

        // 6. 加密 text 文件
        console.log(`加密 text 文件: ${textName}`);
        result = runSecureconfigCommand('encrypt', textName, '--type', 'text');
        printResult('加密 text 文件', result);

        // 7. 解密 text 文件
        console.log(`解密 text 文件: ${textName}`);
        result = runSecureconfigCommand('decrypt', textName, '--type', 'text');
        printResult('解密 text 文件', result);

        // 8. 创建 binary 文件
        const binaryName = 'demo_bin';
        console.log(`创建 binary 文件: ${binaryName}`);
        result = runSecureconfigCommand('create', binaryName, '--type', 'binary', '--force');
        printResult('创建 binary 文件', result);

        // 9. 保存明文内容到 binary 文件（写入二进制数据）
        const binaryPath = path.join('configs', `${binaryName}.bin`);
        const buffer = Buffer.from([0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07]);
        fs.writeFileSync(binaryPath, buffer);
        console.log(`已写入明文内容到 ${binaryPath}`);

        // 10. 加密 binary 文件
        console.log(`加密 binary 文件: ${binaryName}`);
        result = runSecureconfigCommand('encrypt', binaryName, '--type', 'binary');
        printResult('加密 binary 文件', result);

        // 11. 解密 binary 文件
        console.log(`解密 binary 文件: ${binaryName}`);
        result = runSecureconfigCommand('decrypt', binaryName, '--type', 'binary');
        printResult('解密 binary 文件', result);

        console.log(`\n${colors.fg.cyan}===== 第二部分: 原地加解密操作 (使用 --inplace 参数) =====${colors.reset}`);

        // 12. 创建原地加密演示文件
        const inplaceName = 'inplace_demo';
        const jsonPath = path.join('configs', `${inplaceName}.json`);
        const backupPath = path.join('configs', `${inplaceName}_backup.json`);
        
        console.log(`创建原地加密演示 json 文件: ${inplaceName}`);
        result = runSecureconfigCommand('create', inplaceName, '--type', 'json', '--force');
        printResult('创建原地加密演示文件', result);

        // 13. 设置演示文件内容
        console.log(`设置演示文件值: ${inplaceName}`);
        runSecureconfigCommand('set-value', inplaceName, 'demo.name', '原地加密演示');
        result = runSecureconfigCommand('set-value', inplaceName, 'demo.description', '这是一个测试原地加密功能的文件');

        // 14. 解密后备份原始明文文件（用于对比）
        result = runSecureconfigCommand('decrypt', inplaceName, '--type', 'json');
        fs.copyFileSync(jsonPath, backupPath);
        printResult('设置演示文件值', result);
        console.log(`已备份明文文件到 ${backupPath}`);

        // 15. 原地加密
        console.log(`原地加密文件: ${inplaceName} (使用 --inplace 参数)`);
        result = runSecureconfigCommand('encrypt', inplaceName, '--type', 'json', '--inplace');
        printResult('原地加密', result);

        // 16. 验证原地加密结果
        const encryptedJsonExists = fs.existsSync(path.join('configs', `${inplaceName}.json.enc`));
        const originalJsonExists = fs.existsSync(jsonPath);
        console.log(`加密文件 (${inplaceName}.json.enc) 是否存在? ${encryptedJsonExists}`);
        console.log(`原始文件 (${inplaceName}.json) 是否存在? ${originalJsonExists} (原地加密，应该存在)`);

        // 17. 原地解密
        console.log(`原地解密文件: ${inplaceName} (使用 --inplace 参数)`);
        result = runSecureconfigCommand('decrypt', inplaceName, '--type', 'json', '--inplace');
        printResult('原地解密', result);

        // 18. 验证文件是否相同
        let areFilesIdentical = false;
        try {
            const fileContent1 = fs.readFileSync(jsonPath, 'utf8');
            const fileContent2 = fs.readFileSync(backupPath, 'utf8');
            areFilesIdentical = fileContent1 === fileContent2;
        } catch (e) {
            console.log(`比较文件时出错: ${e.message}`);
        }
        
        console.log(`原地加解密后的文件与原始文件是否相同? ${areFilesIdentical}`);

        // 19. 清理演示文件
        console.log(`\n${colors.fg.cyan}===== 清理演示文件 =====${colors.reset}`);
        const filesToDelete = [jsonName, textName, binaryName, inplaceName];
        
        for (const name of filesToDelete) {
            console.log(`删除文件: ${name}`);
            runSecureconfigCommand('delete', name, '--type', 'json');
        }
        
        if (fs.existsSync(backupPath)) {
            fs.unlinkSync(backupPath);
            console.log(`已删除备份文件: ${backupPath}`);
        }

        // 20. 演示 get-value/set-value 仅支持 json 的限制
        console.log(`\n${colors.fg.cyan}===== 演示 get-value/set-value 仅支持 json 的限制 =====${colors.reset}`);
        
        console.log(`尝试对 text 文件使用 get-value (应报错)`);
        try {
            result = runSecureconfigCommand('get-value', textName, 'app.version', '--type', 'text');
        } catch (e) {
            result = { status: 'error', message: e.message };
        }
        printResult('get-value 用于 text 类型', result);

        console.log(`尝试对 binary 文件使用 get-value (应报错)`);
        try {
            result = runSecureconfigCommand('get-value', binaryName, 'app.version', '--type', 'binary');
        } catch (e) {
            result = { status: 'error', message: e.message };
        }
        printResult('get-value 用于 binary 类型', result);

        // 计算总耗时
        const endTime = Date.now();
        const totalTime = (endTime - startTime) / 1000;
        console.log(`\n${colors.fg.green}全部演示完成，总耗时: ${totalTime.toFixed(2)} 秒${colors.reset}`);
    } catch (error) {
        console.error(`${colors.fg.red}执行演示时发生错误: ${error.message}${colors.reset}`);
        console.error(error.stack);
        process.exit(1);
    }
}

main().catch(err => {
    console.error(`未捕获的错误: ${err.message}`);
    process.exit(1);
});

/*
使用方法:
1. 确保已安装SecureConfig工具
2. 确保已安装Node.js
3. 运行: node demo/nodejs_demo.js
*/ 